<template>
    <el-form label-width="120px" ref="formRefs" :model="spuInfo" :rules="rules">
      <!--SPU名称-->
      <el-form-item label="SPU名称" prop="spuName">
        <el-input placeholder="请输入SPU名称" v-model="spuInfo.spuName"></el-input>
      </el-form-item>
      <!--SPU品牌-->
      <el-form-item label="SPU品牌" prop="tmId">
        <el-select placeholder="请选择" v-model="spuInfo.tmId">
          <el-option v-for="(tm,index) in trademarkList" :key="tm.id" :value="tm.id" :label="tm.tmName"></el-option>
        </el-select>
      </el-form-item>
      <!--SPU描述-->
      <el-form-item label="SPU描述" prop="description">
        <el-input type="textarea" placeholder="请输入SPU描述信息" rows="4" v-model="spuInfo.description"></el-input>
      </el-form-item>
      <!--SPU图片-->
      <el-form-item label="SPU图片" prop="spuImageList">
        <el-upload multiple v-model:file-list="spuInfo.spuImageList" :action="`${BASE_URL}/admin/product/fileUpload`" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :on-success="handleSuccess">
          <el-icon>
            <Plus />
          </el-icon>
        </el-upload>
        <el-dialog v-model="dialogVisible">
          <img w-full :src="dialogImageUrl" alt="Preview Image" />
        </el-dialog>
      </el-form-item>
      <!--销售属性-->
      <el-form-item label="销售属性" prop="spuSaleAttrList">
        <el-select :placeholder="saleAttrText" v-model="saleAttrIdName">
          <el-option v-for="(attr,index) in unSelectedSaleAttrList" :key="attr.id" :value="attr.id+'_'+attr.name" :label="attr.name"></el-option>
        </el-select>
        <!--按钮-->
        <el-button type="primary" :icon="Plus" :disabled="!saleAttrIdName" @click="addSaleAttr">添加销售属性</el-button>
        <!--表格-->
        <el-table border row-key="id" :data="spuInfo.spuSaleAttrList" stripe style="width: 100%;margin-top:20px">
          <el-table-column type="index" label="序号" width="80" align="center" />
          <el-table-column prop="saleAttrName" label="属性名" width="150" />
          <el-table-column label="属性值名称列表">
            <template #default="{row,$index}">
              <el-tag type="success" v-for="(item,index) in row.spuSaleAttrValueList" :key="item.id" closable :disable-transitions="false" @close="row.spuSaleAttrValueList.splice(index,1)" style="margin-right:5px">
                {{item.saleAttrValueName}}
              </el-tag>
              <el-input v-if="row.isShowEdit" :ref="(input:any)=>inputRefs[$index]=input" v-model="saleAttrValueName" size="small" @keyup.enter="toView(row)" @blur="toView(row)" style="width:100px" />
              <el-button v-else size="small" @click="toEdit(row,$index)" :icon="Plus"> </el-button>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="150">
            <template #default="{row,$index}">
              <el-button size="small" type="danger" :icon="Delete" @click="spuInfo.spuSaleAttrList.splice($index,1)"></el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
      <!--两个按钮-->
      <el-form-item>
        <el-button type="primary" @click="saveSpuInfo">保存</el-button>
        <el-button @click="emits('setShowStatus',ShowStatus.SPU_LIST)">取消</el-button>
      </el-form-item>
    </el-form>
  </template>
  <script lang="ts">
  export default {
    name: 'SpuForm'
  }
  </script>
  <script lang="ts" setup>
  import { Plus, Delete } from '@element-plus/icons-vue'
  // 引入枚举类型数据
  import { ShowStatus } from '../types'
  // 引入图片相关的数据类型
  import type {
    UploadProps,
    UploadFiles,
    UploadFile,
    FormInstance,
    FormRules
  } from 'element-plus'
  import { ref, reactive, onMounted, nextTick, computed } from 'vue'
  // 引入基础销售属性数组类型和图片数组类型和spu的销售属性数组类型
  import type {
    SpuModel,
    BaseSaleAttrListModel,
    SpuImageListModel,
    SpuSaleAttrListModel,
    SpuSaleAttrModel
  } from '@/api/product/model/spuModel'
  // 引入品牌数组类型
  import type { TrademarkListModel } from '@/api/product/model/trademarkModel'
  // 引入获取所有品牌列表的api接口函数
  import { getTrademarkListAllApi } from '@/api/product/trademark'
  // 引入基础销售属性数组的api接口函数和spu下的销售属性数组的api接口函数和spu下的图片数组的api接口函数
  import {
    getBaseSaleAttrListApi,
    getSpuInfoSaleAttrListApi,
    getSpuInfoImageListApi,
    addOrUpdateSpuInfo
  } from '@/api/product/spu'
  import { ElMessage } from 'element-plus'
  import { useCategoryStore } from '@/stores/category'
  
  const categoryStore = useCategoryStore()
  // 计算出来一个新数组:没有被选中的销售属性对象数组数据
  const unSelectedSaleAttrList = computed(() => {
    return baseSaleAttrList.value.filter(
      (bsa) => !spuInfo.spuSaleAttrList.some((sa) => sa.saleAttrName === bsa.name)
    )
  })
  // 计算出来一个动态的文字提示信息
  const saleAttrText = computed(() => {
    const { length } = unSelectedSaleAttrList.value
    return length > 0 ? `还有${length}个未选择` : '没有啦'
  })
  
  // 用于接收父级组件传递进来的自定义事件
  const emits = defineEmits(['setShowStatus'])
  // 接收父级组件传递过来的spu对象数据
  const props = defineProps<{ currentSpuInfo: SpuModel }>()
  // 定义一个spuInfo对象数据
  const spuInfo = reactive<SpuModel>(props.currentSpuInfo)
  // 定义上传图片的根路径地址
  const BASE_URL = import.meta.env.VITE_API_URL
  // 预览图片的地址
  const dialogImageUrl = ref('')
  // 是否预览的标识
  const dialogVisible = ref(false)
  // 发送4个请求(所有的品牌数组数据/所有的基础的销售属性数组数据/spu下的图片列表数组数据/spu下的销售属性数组数据)-api接口函数
  // 品牌数组的类型/基础销售属性数组类型/spu的图片列表数组类型/spu销售属性数组类型
  // onMounted回调----直接4个
  // 还需要定义可能是4个变量来接收数据
  
  // 定义基础销售属性数组数据
  const baseSaleAttrList = ref<BaseSaleAttrListModel>([])
  // 定义所有品牌的数组数据
  const trademarkList = ref<TrademarkListModel>([])
  // 用来收集选中的销售属性的id和名字
  const saleAttrIdName = ref<string>('')
  
  // 用来收集文本框dom对象的数组
  const inputRefs = ref<HTMLInputElement[]>([])
  // 用来收集销售属性值录入的数据
  const saleAttrValueName = ref<string>('')
  // 定义form的dom对象
  const formRefs = ref<FormInstance>()
  // 验证规则
  const rules = reactive<FormRules>({
    // 验证SPU的名字和和品牌的id和描述信息和spu的图片数组和spu的销售属性数组
    spuName: [{ required: true, message: '必须输入SPU名称', trigger: 'blur' }],
    tmId: [{ required: true, message: '必须选择SPU品牌', trigger: 'change' }],
    description: [
      { required: true, message: '必须输入SPU描述信息', trigger: 'blur' }
    ],
    spuImageList: [
      {
        required: true,
        message: '必须上传SPU图片',
        type: 'array',
        trigger: 'change'
      }
    ],
    spuSaleAttrList: [
      { required: true, message: '必须添加SPU销售属性', type: 'array' }
    ]
  })
  
  // 组件加载后获取所有的品牌列表数据
  onMounted(async () => {
    trademarkList.value = await getTrademarkListAllApi()
  })
  // 组件加载后获取所有的基础销售属性列表数据
  onMounted(async () => {
    baseSaleAttrList.value = await getBaseSaleAttrListApi()
  })
  // 组件加载后获取spu下所有的销售属性列表数据
  onMounted(async () => {
    // 判断id是否存在----将来有一天实现spu添加的时候,需要调用下面的接口
    const id = spuInfo.id as number
    if (!id) return
    spuInfo.spuSaleAttrList = await getSpuInfoSaleAttrListApi(id)
  })
  // 组件加载后获取spu下所有的图片列表数据
  onMounted(async () => {
    const id = spuInfo.id as number
    if (!id) return
    const spuImageList = await getSpuInfoImageListApi(id)
    // 需要把图片对象中重新的添加name和url属性,页面中的图片才可以展示,为啥呢?element-plus内部的图片展示必须使用name和url属性
    spuInfo.spuImageList = spuImageList.map((item) => ({
      ...item,
      name: item.imgName,
      url: item.imgUrl
    }))
  })
  
  // 上传图片成功后的方法:把上传成功的图片地址重新的保存一下
  const handleSuccess: UploadProps['onSuccess'] = (
    res,
    file: UploadFile,
    fileList: UploadFiles
  ) => {
    // 需要做的事:保存上传成功的图片
    spuInfo.spuImageList = fileList as any
  }
  // 移除图片的回调
  const handleRemove: UploadProps['onRemove'] = (
    uploadFile: UploadFile,
    fileList: UploadFiles
  ) => {
    spuInfo.spuImageList = fileList as any
  }
  // 预览图片的回调
  const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
    dialogImageUrl.value = uploadFile.url!
    dialogVisible.value = true
  }
  
  // 查看模式
  const toView = (saleAttr: SpuSaleAttrModel) => {
    // 判断用户输入的数据是否有效
    if (!saleAttrValueName.value || !saleAttrValueName.value.trim()) {
      ElMessage.warning('请输入有效数据')
      saleAttrValueName.value = ''
      saleAttr.isShowEdit = false
      return
    }
    // 判断用户输入的数据和之前存在的数据是否相同
    const isRepeat = saleAttr.spuSaleAttrValueList.some(
      (item) => item.saleAttrValueName === saleAttrValueName.value
    )
    if (isRepeat) {
      ElMessage.warning('数据有重复的')
    } else {
      // 把这个数据添加到属性值对象数组中
      saleAttr.spuSaleAttrValueList.push({
        baseSaleAttrId: saleAttr.baseSaleAttrId,
        saleAttrValueName: saleAttrValueName.value
      })
    }
    // 查看模式
    saleAttrValueName.value = ''
    saleAttr.isShowEdit = false
  }
  // 编辑模式
  const toEdit = (saleAttr: SpuSaleAttrModel, index: number) => {
    saleAttr.isShowEdit = true
    // 自动获取焦点
    nextTick(() => {
      inputRefs.value[index].focus()
    })
  }
  
  // 添加销售属性操作
  const addSaleAttr = () => {
    // 把id和名字的数据中的_切掉
    const [id, name] = saleAttrIdName.value.split('_')
    // 把id和name组成一个对象,方法在spuInfo对象的spuSaleAttrList数组中
    spuInfo.spuSaleAttrList.push({
      baseSaleAttrId: +id,
      saleAttrName: name,
      spuSaleAttrValueList: []
    })
    saleAttrIdName.value = '' // 清空选中的内容
  }
  // 保存spu操作
  const saveSpuInfo = async () => {
    await formRefs.value.validate()
    // 过滤销售属性数据
    spuInfo.spuSaleAttrList = spuInfo.spuSaleAttrList.filter((item) => {
      // 判断里面的属性值数组是否有数据
      if (item.spuSaleAttrValueList.length === 0) return false
      delete item.isShowEdit
      return true
    })
    console.log(spuInfo.spuImageList)
    // 过滤图片数据
    spuInfo.spuImageList = spuInfo.spuImageList.map((item) => ({
      imgName: item.name as string, // 图片名字
      imgUrl: item.response ? item.response.data : item.url, // 图片地址
      spuId: spuInfo.id
    }))
    // 二次验证销售属性数据
    if (spuInfo.spuSaleAttrList.length === 0) {
      ElMessage.warning('必须添加至少一个SPU的销售属性')
      return
    }
    // 更新三级分类的id
    spuInfo.category3Id = categoryStore.getCategory3Id
    try {
      // 调用接口,发送请求
      await addOrUpdateSpuInfo(spuInfo)
      ElMessage.success('保存成功')
    } catch (error) {
      console.log('出错了')
    }
  // 关闭界面,回到列表页,数据重置,刷新
  emits('setShowStatus',ShowStatus.SPU_LIST)
    
  }
  </script>
  <style scoped>
  </style>